home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
nihcl-30.lha
/
nihcl-3.0
/
lib
/
Class.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-19
|
9KB
|
357 lines
/* Class.c -- implementation of class descriptor objects
THIS SOFTWARE FITS THE DESCRIPTION IN THE U.S. COPYRIGHT ACT OF A
"UNITED STATES GOVERNMENT WORK". IT WAS WRITTEN AS A PART OF THE
AUTHOR'S OFFICIAL DUTIES AS A GOVERNMENT EMPLOYEE. THIS MEANS IT
CANNOT BE COPYRIGHTED. THIS SOFTWARE IS FREELY AVAILABLE TO THE
PUBLIC FOR USE WITHOUT A COPYRIGHT NOTICE, AND THERE ARE NO
RESTRICTIONS ON ITS USE, NOW OR SUBSEQUENTLY.
Author:
K. E. Gorlen
Bg. 12A, Rm. 2033
Computer Systems Laboratory
Division of Computer Research and Technology
National Institutes of Health
Bethesda, Maryland 20892
Phone: (301) 496-1111
uucp: uunet!nih-csl!kgorlen
Internet: kgorlen@alw.nih.gov
September, 1985
Function:
Functions pertaining to class Class. Most of these are defined inline
in object.h.
Modification History:
$Log: Class.c,v $
* Revision 3.0 90/05/20 00:19:16 kgorlen
* Release for 1st edition.
*
*/
#include <stdarg.h>
#include "Object.h"
#include "String.h"
#include "Dictionary.h"
#include "Assoc.h"
#include "OrderedCltn.h"
#include "IdentSet.h"
#include "nihclIO.h"
#include "OIOTbl.h"
extern const int NIHCL_RDBADSIG,NIHCL_RDBADTYP,NIHCL_RDWRONGCLASS,NIHCL_RDUNKCLASS,NIHCL_UNKCLASS;
#define THIS Class
#define BASE Object
#define BASE_CLASSES BASE::desc()
#define MEMBER_CLASSES
#define VIRTUAL_BASE_CLASSES Object::desc()
/* DEFINE_CLASS */
Object* Class::reader(OIOin&)
{
setError(NIHCL_RDUNKCLASS,DEFAULT,"Class");
return 0;
}
Object* Class::reader(OIOifd&)
{
setError(NIHCL_RDUNKCLASS,DEFAULT,"Class");
return 0;
}
static Class class_Class("Class",
ClassList(0,BASE_CLASSES,0), ClassList(0,0), ClassList(0,0),
1, // version
"$Header: /afs/alw.nih.gov/unix/sun4_40c/usr/local/src/nihcl-3.0/share/lib/RCS/Class.c,v 3.0 90/05/20 00:19:16 kgorlen Rel $",
sizeof(Class), Class::reader, Class::reader, NULL, NULL);
const Class* Class::desc() { return &class_Class; }
const Class* Class::isA() const { return &class_Class; }
Object* Class::shallowCopy() const { return new Class(*this); }
_DEFINE_CASTDOWN(Class)
// head of the list of all Classes, built by the static constructor of class Class
static Class* allClasses =0;
static Dictionary classDictionary; // Dictionary of all Classes
Dictionary& Class::dictionary = classDictionary;
unsigned long Class::readFrom_level = 0; // reset readFromTbl when 0
unsigned long Class::storeOn_level = 0; // reset storeOnTbl when 0
unsigned long Class::addObjectFlag = 0; // add object to readFromTbl when 0
IdentSet* Class::storeVBaseTbl = 0; // table used by storeOn()
ReadFromTbl* Class::readFromTbl = 0; // tables used by readFrom()
StoreOnTbl* Class::storeOnTbl = 0; // tables used by storeOn()
#ifdef sparc
// Use magic name to make stdarg work
#define arg0 __builtin_va_alist
#endif
ClassList::ClassList(const char* arg0, ...)
{
va_list ap;
unsigned nargs = 0;
va_start(ap, arg0);
do nargs++; while (va_arg(ap, Class*));
va_end(ap);
Class** p = clp = new Class*[nargs];
va_start(ap, arg0);
while (nargs--) *p++ = va_arg(ap, Class*);
va_end(ap);
}
Class::Class(const char* name,
const ClassList& bases, const ClassList& members, const ClassList& vbases,
unsigned version, const char* ident, unsigned size,
Object* (*reader)(OIOin&),
Object* (*binreader)(OIOifd&),
initorTy initor1, initorTy initor2)
:
class_name(name),
class_ident(ident),
class_bases(bases.clp),
class_members(members.clp),
class_vbases(vbases.clp),
class_version(version),
inst_size(size),
inst_reader(reader),
inst_binreader(binreader),
class_initor2(initor2)
{
nextClass = allClasses; allClasses = this;
class_signature = 0;
class_number = 0;
// if (initor1 != 0) initor1(*this); MASSCOMP cc bug
initorTy initfun = initor1;
if (initfun != 0) initfun(*this);
}
Class::Class(const Class& c)
:
class_name(c.class_name),
class_bases(c.class_bases),
class_members(c.class_members),
class_vbases(c.class_vbases),
class_version(c.class_version),
class_ident(c.class_ident),
class_signature(c.class_signature),
inst_size(c.inst_size),
inst_reader(c.inst_reader),
inst_binreader(c.inst_binreader),
class_initor2(c.class_initor2),
class_number(c.class_number)
{
}
Class::Class(OIOifd&)
:
class_bases(0),
class_members(0),
class_vbases(0),
class_version(0),
inst_size(0),
inst_reader(0),
inst_binreader(0),
class_initor2(0)
{
}
Class::Class(OIOin&)
:
class_bases(0),
class_members(0),
class_vbases(0),
class_version(0),
inst_size(0),
inst_reader(0),
inst_binreader(0),
class_initor2(0)
{
}
int Class::compare(const Object& ob) const // compare Class names
{
assertArgSpecies(ob,class_Class,"compare");
return strcmp(name(),castdown(ob).name());
}
unsigned Class::hash() const { return (const unsigned)this; }
bool Class::isEqual(const Object& ob) const { return this == castdown(&ob); }
bool Class::_isKindOf(const Class& clid) const
{
if (this == &clid) return YES;
const Class** bp = baseClasses();
while (*bp) if ((*bp++)->_isKindOf(clid)) return YES;
return NO;
}
void Class::deepenShallowCopy() { shouldNotImplement("deepenShallowCopy"); }
void Class::dumpOn(ostream& strm) const
{
strm << className() << '[' << name() << '\n';
strm << "ident: " << ident() << '\n';
strm << "version: " << version() << '\n';
strm << "signature: " << signature() << '\n';
strm << "number: " << number() << '\n';
strm << "base classes:";
const Class** p = baseClasses();
while (*p) strm << ' ' << (*p++)->name();
strm << '\n';
strm << "member classes:";
p = memberClasses();
while (*p) strm << ' ' << (*p++)->name();
strm << '\n';
strm << "virtual base classes:";
p = virtualBaseClasses();
while (*p) strm << ' ' << (*p++)->name();
strm << '\n';
strm << "]\n";
}
void Class::printOn(ostream& strm) const { strm << class_name; }
unsigned Class::size() const { return inst_size; }
void Class::addSignature(unsigned long s)
{
// Assumes that an unsigned long is at least 32 bits
class_signature = ((class_signature << 3) + (class_signature >> (32-3) & 7) + s) & 0xFFFFFFFF;
}
void Class::computeSignature()
{
if (this == Object::desc()) {
class_signature = class_version;
return;
}
Class** p = (Class**)class_bases;
while (*p) addSignature((*p++)->signature());
if (class_signature == 0) class_signature++;
p = (Class**)class_members;
while (*p) addSignature((*p++)->signature());
if (class_version != 0) addSignature(class_version);
if (class_signature == 0) class_signature++;
}
const Class* Class::lookup(const char* name)
// Find the class descriptor for class "name"
{
LookupKey* asc = dictionary.assocAt(String(name));
if (asc == 0) return 0;
return castdown(asc->value());
}
class ReadFromTblMgr {
friend Object* Class::readFrom(OIOin& strm) const;
friend Object* Class::readFrom(OIOifd& fd) const;
ReadFromTblMgr() {
if (Class::readFrom_level++ == 0) Class::readFromTbl = new ReadFromTbl;
}
~ReadFromTblMgr() {
if (--Class::readFrom_level == 0) {
delete Class::readFromTbl;
Class::readFromTbl = 0;
}
}
};
Object* Class::readFrom(OIOin& strm) const
{
ReadFromTblMgr tbl;
return strm.readObject(*this);
}
Object* Class::readObject(OIOin& strm) const
// Called by OIOin::readObject()
{
#ifdef DEBUG_OBJIO
cerr << "readFrom: read instance of class " << name();
#endif
addObjectFlag = 0; // causes Object::Object(OIOin&) to do Class::readFromTbl->add()
return (*inst_reader)(strm);
}
Object::Object(OIOin&)
{
if (Class::addObjectFlag++ == 0) {
int objectNum = Class::readFromTbl->add(*this); // add object to readFromTbl
#ifdef DEBUG_OBJIO
cerr << ", object #" << objectNum << "\n";
#endif
}
}
Object* Class::readFrom(OIOifd& fd) const
{
ReadFromTblMgr tbl;
return fd.readObject(*this);
}
Object* Class::readObject(OIOifd& fd) const
// Called by OIOifd::readObject()
{
#ifdef DEBUG_OBJIO
cerr << "readFrom: read instance of class " << name();
#endif
addObjectFlag = 0; // causes Object::Object(OIOifd&) to do Class::readFromTbl->add();
return (*inst_binreader)(fd);
}
Object::Object(OIOifd&)
{
if (Class::addObjectFlag++ == 0) {
int objectNum = Class::readFromTbl->add(*this); // add object to readFromTbl
#ifdef DEBUG_OBJIO
cerr << ", object #" << objectNum << "\n";
#endif
}
}
void Class::initialize() // class initialization
{
register Class* clp = allClasses; // add all classes to class dictionary
#ifdef DEBUG
while (clp != NULL) { clp->dumpOn(); clp = clp->nextClass; }
clp = allClasses;
#endif
while (clp != NULL) {
clp->signature(); // compute class signatures
dictionary.add(*new Assoc(*new String(clp->name()), *clp));
clp = clp->nextClass;
}
clp = allClasses; // call the initor2 functions
while (clp != NULL) {
if (clp->class_initor2 != 0) (*clp->class_initor2)(*clp);
clp = clp->nextClass;
}
}
bool Class::_storeVBase(void* p)
{
if (storeVBaseTbl == 0) {
storeVBaseTbl = new IdentSet(256);
storeVBaseTbl->add(*(Object*)p);
return YES;
}
if (storeVBaseTbl->includes(*(Object*)p)) return NO;
storeVBaseTbl->add(*(Object*)p);
return YES;
}
void Class::storer(OIOout&) const { shouldNotImplement("storer"); }
void Class::storer(OIOofd&) const { shouldNotImplement("storer"); }